using DeviceCommons.DeviceMessages.Enums;
using DeviceCommons.DeviceMessages.Models.V1;
using DeviceCommons.Validation;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Security.Cryptography;

namespace DeviceCommons.DeviceMessages.Factories
{
    /// <summary>
    /// 状态工厂注册帮助类
    /// </summary>
    public static class StateFactoryRegistrationHelper
    {
        /// <summary>
        /// 为指定设备类型注册状态工厂
        /// </summary>
        /// <typeparam name="TFactory">工厂类型</typeparam>
        /// <param name="services">服务集合</param>
        /// <param name="deviceType">设备类型</param>
        /// <param name="lifetime">服务生命周期</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection RegisterStateFactory<TFactory>(
            this IServiceCollection services,
            byte deviceType,
            ServiceLifetime lifetime = ServiceLifetime.Transient)
            where TFactory : class, IStateFactory
        {
            // 注册工厂类型到DI容器
            services.Add(new ServiceDescriptor(typeof(TFactory), typeof(TFactory), lifetime));
            
            // 注册状态工厂注册信息
            services.AddSingleton(new StateFactoryRegistration(deviceType, typeof(TFactory)));
            
            return services;
        }

        /// <summary>
        /// 为指定设备类型注册状态工厂（使用工厂方法）
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="deviceType">设备类型</param>
        /// <param name="factoryProvider">工厂提供者</param>
        /// <param name="lifetime">服务生命周期</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection RegisterStateFactory(
            this IServiceCollection services,
            byte deviceType,
            Func<IServiceProvider, IStateFactory> factoryProvider,
            ServiceLifetime lifetime = ServiceLifetime.Transient)
        {
            // 生成唯一的服务类型
            var serviceType = typeof(IStateFactory);
            var implementationType = typeof(DelegateStateFactory);
            
            // 注册委托工厂
            services.Add(new ServiceDescriptor(
                implementationType, 
                provider => new DelegateStateFactory(factoryProvider(provider)), 
                lifetime));
            
            // 注册状态工厂注册信息
            services.AddSingleton(new StateFactoryRegistration(deviceType, implementationType));
            
            return services;
        }

        /// <summary>
        /// 批量注册状态工厂
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="registrations">工厂注册配置</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection RegisterStateFactories(
            this IServiceCollection services,
            params (byte deviceType, Type factoryType, ServiceLifetime lifetime)[] registrations)
        {
            foreach (var (deviceType, factoryType, lifetime) in registrations)
            {
                if (!typeof(IStateFactory).IsAssignableFrom(factoryType))
                {
                    throw new DeviceMessageValidationException(
                        ValidationErrorType.InvalidFactoryTypeConfiguration,
                        $"工厂类型 {factoryType.Name} 必须实现 IStateFactory 接口",
                        nameof(factoryType),
                        "IStateFactory 接口实现",
                        factoryType.Name);
                }

                // 注册工厂类型
                services.Add(new ServiceDescriptor(factoryType, factoryType, lifetime));
                
                // 注册状态工厂注册信息
                services.AddSingleton(new StateFactoryRegistration(deviceType, factoryType));
            }

            return services;
        }

        /// <summary>
        /// 使用配置注册状态工厂
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="configure">配置委托</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection ConfigureStateFactories(
            this IServiceCollection services,
            Action<StateFactoryRegistrationBuilder> configure)
        {
            var builder = new StateFactoryRegistrationBuilder(services);
            configure(builder);
            return services;
        }
    }

    /// <summary>
    /// 状态工厂注册构建器
    /// </summary>
    public class StateFactoryRegistrationBuilder
    {
        private readonly IServiceCollection _services;

        public StateFactoryRegistrationBuilder(IServiceCollection services)
        {
            _services = services;
        }

        /// <summary>
        /// 注册状态工厂
        /// </summary>
        /// <typeparam name="TFactory">工厂类型</typeparam>
        /// <param name="deviceType">设备类型</param>
        /// <param name="lifetime">服务生命周期</param>
        /// <returns>构建器</returns>
        public StateFactoryRegistrationBuilder AddFactory<TFactory>(
            byte deviceType,
            ServiceLifetime lifetime = ServiceLifetime.Transient)
            where TFactory : class, IStateFactory
        {
            _services.RegisterStateFactory<TFactory>(deviceType, lifetime);
            return this;
        }

        /// <summary>
        /// 注册状态工厂（使用工厂方法）
        /// </summary>
        /// <param name="deviceType">设备类型</param>
        /// <param name="factoryProvider">工厂提供者</param>
        /// <param name="lifetime">服务生命周期</param>
        /// <returns>构建器</returns>
        public StateFactoryRegistrationBuilder AddFactory(
            byte deviceType,
            Func<IServiceProvider, IStateFactory> factoryProvider,
            ServiceLifetime lifetime = ServiceLifetime.Transient)
        {
            _services.RegisterStateFactory(deviceType, factoryProvider, lifetime);
            return this;
        }
    }

    /// <summary>
    /// 委托状态工厂包装器
    /// </summary>
    internal class DelegateStateFactory : IStateFactory
    {
        private readonly IStateFactory _factory;

        public DelegateStateFactory(IStateFactory factory)
        {
            _factory = factory;
        }

        public IDeviceMessageInfoReadingState CreateState(byte sid, object value, StateValueTypeEnum? valueType = null)
        {
            return _factory.CreateState(sid, value, valueType);
        }

        public IDeviceMessageInfoReadingStates CreateStates(params StateValueTypeEnum[] types)
        {
            return _factory.CreateStates(types);
        }
    }
}